import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import { createError } from './errorHandler';
import { User, IUser } from '../models/User';
import { logger } from '../utils/logger';
import config from '../config/env';

export interface AuthRequest extends Request {
  user?: {
    id: string;
    email: string;
    name: string;
    role: 'admin' | 'teacher' | 'student';
  };
}

/**
 * JWT认证中间件
 */
export const authMiddleware = async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    // 从请求头获取令牌
    const authHeader = req.header('Authorization');
    const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;
    
    if (!token) {
      logger.warn('认证失败: 缺少令牌', { 
        path: req.path, 
        method: req.method,
        ip: req.ip 
      });
      return next(createError('需要登录访问', 401));
    }

    // 验证令牌
    const decoded = jwt.verify(token, config.JWT_SECRET) as { 
      userId: string; 
      type: string; 
      iat: number; 
      exp: number; 
    };

    // 检查令牌类型
    if (decoded.type !== 'access') {
      logger.warn('认证失败: 令牌类型错误', { 
        type: decoded.type,
        userId: decoded.userId 
      });
      return next(createError('无效的访问令牌', 401));
    }

    // 获取用户信息
    const user = await User.findById(decoded.userId).select('-password -passwordHistory');
    if (!user) {
      logger.warn('认证失败: 用户不存在', { userId: decoded.userId });
      return next(createError('用户不存在', 401));
    }

    // 检查账户状态
    if (user.isLocked) {
      logger.warn('认证失败: 账户被锁定', { userId: decoded.userId });
      return next(createError('账户已被锁定', 423));
    }

    // 将用户信息添加到请求对象
    req.user = {
      id: (user._id as any).toString(),
      email: user.email,
      name: user.name,
      role: user.role as 'admin' | 'teacher' | 'student'
    };

    logger.debug('用户认证成功', { 
      userId: user._id, 
      role: user.role,
      path: req.path 
    });

    next();
  } catch (error: any) {
    logger.warn('认证失败', { 
      error: error.message,
      path: req.path,
      method: req.method 
    });

    if (error.name === 'JsonWebTokenError') {
      return next(createError('无效的访问令牌', 401));
    } else if (error.name === 'TokenExpiredError') {
      return next(createError('访问令牌已过期', 401));
    } else {
      return next(createError('认证失败', 401));
    }
  }
};

/**
 * 管理员权限中间件
 */
export const adminMiddleware = (req: AuthRequest, res: Response, next: NextFunction) => {
  if (!req.user) {
    return next(createError('用户未认证', 401));
  }

  if (req.user.role !== 'admin') {
    logger.warn('权限不足: 需要管理员权限', { 
      userId: req.user.id, 
      role: req.user.role,
      path: req.path 
    });
    return next(createError('需要管理员权限', 403));
  }

  next();
};

/**
 * 教师权限中间件
 */
export const teacherMiddleware = (req: AuthRequest, res: Response, next: NextFunction) => {
  if (!req.user) {
    return next(createError('用户未认证', 401));
  }

  if (!['admin', 'teacher'].includes(req.user.role)) {
    logger.warn('权限不足: 需要教师权限', { 
      userId: req.user.id, 
      role: req.user.role,
      path: req.path 
    });
    return next(createError('需要教师或管理员权限', 403));
  }

  next();
};

/**
 * 资源所有者权限中间件工厂
 */
export const ownerMiddleware = (resourceIdParam: string = 'id') => {
  return (req: AuthRequest, res: Response, next: NextFunction) => {
    if (!req.user) {
      return next(createError('用户未认证', 401));
    }

    // 管理员可以访问所有资源
    if (req.user.role === 'admin') {
      return next();
    }

    // 检查资源所有权
    const resourceOwnerId = req.params[resourceIdParam] || req.body.userId;
    if (req.user.id !== resourceOwnerId) {
      logger.warn('权限不足: 非资源所有者', { 
        userId: req.user.id, 
        resourceOwnerId,
        path: req.path 
      });
      return next(createError('只能访问自己的资源', 403));
    }

    next();
  };
};

/**
 * 角色权限检查中间件工厂
 */
export const roleMiddleware = (allowedRoles: ('admin' | 'teacher' | 'student')[]) => {
  return (req: AuthRequest, res: Response, next: NextFunction) => {
    if (!req.user) {
      return next(createError('用户未认证', 401));
    }

    if (!allowedRoles.includes(req.user.role)) {
      logger.warn('权限不足: 角色不匹配', { 
        userId: req.user.id, 
        userRole: req.user.role,
        allowedRoles,
        path: req.path 
      });
      return next(createError(`需要以下角色之一: ${allowedRoles.join(', ')}`, 403));
    }

    next();
  };
};

/**
 * 可选认证中间件（不强制要求登录）
 */
export const optionalAuthMiddleware = async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const authHeader = req.header('Authorization');
    const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;
    
    if (!token) {
      return next();
    }

    const decoded = jwt.verify(token, config.JWT_SECRET) as { 
      userId: string; 
      type: string; 
    };

    if (decoded.type === 'access') {
      const user = await User.findById(decoded.userId).select('-password -passwordHistory');
      if (user && !user.isLocked) {
        req.user = {
          id: (user._id as any).toString(),
          email: user.email,
          name: user.name,
          role: user.role as 'admin' | 'teacher' | 'student'
        };
      }
    }
  } catch (error) {
    // 忽略认证错误，继续执行
  }
  
  next();
};